home *** CD-ROM | disk | FTP | other *** search
- /*
- * readiff.c V2.1
- *
- * read IFF ILBM/ANIM files
- *
- * (c) 1990-1993 Stefan Becker
- */
-
- #include "ToolManagerLib.h"
-
- /* Bitmap header (BMHD) structure */
- struct BitMapHeader {
- UWORD w,h; /* Width, height in pixels */
- WORD x,y;
- UBYTE nplanes; /* Number of planes */
- UBYTE Masking; /* Masking */
- UBYTE Compression; /* Compression algorithm */
- UBYTE pad1;
- UWORD TransparentColor;
- UBYTE XAspect,YAspect;
- WORD PageWidth, PageHeight;
- };
- #define MSK_HASMASK 1
- #define COMP_NO 0
- #define COMP_BYTERUN1 1
- #define BPR(w) ((((w)+15)>>4)<<1) /* Bytes per row formula */
-
- /* Animation header (ANHD) structure */
- struct AnimHeader {
- UBYTE operation; /* We only accept code 5 */
- UBYTE mask;
- UWORD w,h;
- WORD x,y;
- ULONG abstime;
- ULONG reltime; /* timing in jiffies (1/60 seconds) */
- UBYTE interleave; /* We only accept 0(=2), 1 & 2 */
- UBYTE pad0;
- ULONG bits;
- };
-
- /* IFF ID's */
- #define ID_ILBM MAKE_ID('I','L','B','M')
- #define ID_BMHD MAKE_ID('B','M','H','D')
- #define ID_BODY MAKE_ID('B','O','D','Y')
- #define ID_ANIM MAKE_ID('A','N','I','M')
- #define ID_ANHD MAKE_ID('A','N','H','D')
- #define ID_DLTA MAKE_ID('D','L','T','A')
-
- /* Read IFF ILBM BODY Chunk */
- static BOOL ReadBODYChunk(struct IFFHandle *iff, struct BitMapHeader *bmhd,
- UBYTE *dest, ULONG bpr, ULONG planeoff)
- {
- UBYTE *src;
- ULONG size=CurrentChunk(iff)->cn_Size;
- BOOL rc=FALSE;
-
- DEBUG_PRINTF("IFF: Read BODY chunk\n");
-
- /* Get memory for BODY chunk contents */
- if (src=AllocMem(size,MEMF_PUBLIC)) {
- /* Read in the complete BODY chunk */
- if (ReadChunkBytes(iff,src,size)==size) {
- register UBYTE *sp=src;
- ULONG row;
- BOOL ncomp=bmhd->Compression==COMP_NO;
- BOOL mask=bmhd->Masking==MSK_HASMASK;
-
- /* Read data row by row */
- for (row=0; row<bmhd->h; row++) {
- ULONG pl;
-
- /* Read data plane by plane */
- for (pl=0; pl<bmhd->nplanes; pl++) {
- UBYTE *dp;
-
- /* Calculate destination pointer */
- dp=dest+pl*planeoff+row*bpr;
-
- /* Compressed? */
- if (ncomp) {
- /* No compression */
- UBYTE k;
-
- for (k=bpr; k--;) *dp++=*sp++; /* Copy all bytes */
- } else {
- /* Byte Run compression */
- ULONG rem=bpr;
-
- /* Row not completed */
- while (rem) {
- BYTE k=*sp++; /* Read compression code */
-
- if (k>=0) {
- /* Literal copy */
- if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
-
- while (k--) *dp++=*sp++; /* Copy the following k+1 bytes */
- } else if (k!=-128) { /* Code -128 == No Operation */
- /* Byte run encoded */
- UBYTE byte;
-
- k=-k;
- if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
-
- byte=*sp++; /* Get byte */
- while (k--) *dp++=byte; /* Copy this byte -k+1 times */
- }
- }
- }
- }
-
- /* Skip mask plane */
- if (mask)
- /* Compressed? */
- if (ncomp)
- /* No compression */
- sp+=bpr;
- else {
- /* Byte Run compression */
- ULONG rem=bpr;
-
- /* Row not completed */
- while (rem) {
- BYTE k=*sp++; /* Read compression code */
-
- if (k>=0) {
- /* Literal copy */
- if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
- sp+=k; /* Skip the following k+1 bytes */
- } else if (k!=-128) { /* Code -128 == No Operation */
- /* Byte run encoded */
- k=-k;
- if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
- sp++; /* Skip this byte */
- }
- }
- }
- }
-
- /* All OK */
- rc=TRUE;
- comperr: /* Got a compression error */
- }
- FreeMem(src,size);
- }
- return(rc);
- }
-
- /* Read IFF ILBM Chunk */
- static struct TMImageData *ReadILBMChunk(struct IFFHandle *iff)
- {
- struct TMImageData *tmid;
-
- DEBUG_PRINTF("IFF: Read ILBM chunk\n");
-
- /* Allocate memory for main data structure */
- if (tmid=AllocMem(sizeof(struct TMImageData),MEMF_PUBLIC|MEMF_CLEAR)) {
-
- /* BMHD: FORM ILBM property chunk */
- if (!PropChunk(iff,ID_ILBM,ID_BMHD) &&
-
- /* BODY: FORM ILBM image data chunk */
- !StopChunk(iff,ID_ILBM,ID_BODY) &&
-
- /* FORM: begin of next context */
- !StopOnExit(iff,ID_ILBM,ID_FORM) &&
-
- /* Chunk types set, start parsing */
- !ParseIFF(iff,IFFPARSE_SCAN)) {
-
- struct StoredProperty *sp;
-
- /* BMHD chunk found? */
- if (sp=FindProp(iff,ID_ILBM,ID_BMHD)) {
- struct BitMapHeader *bmhd=(struct BitMapHeader *) sp->sp_Data;
-
- /* Check compression type */
- if ((bmhd->Compression==COMP_NO) || (bmhd->Compression==COMP_BYTERUN1)) {
- struct TMImageNode *tmin;
-
- /* Alloc memory for TMImageNode */
- if (tmin=AllocMem(sizeof(struct TMImageNode),MEMF_PUBLIC|MEMF_CLEAR)) {
- ULONG bpr,planeoff,size;
-
- /* Calculate sizes */
- bpr=BPR(bmhd->w); /* Bytes per row */
- planeoff=bpr*bmhd->h; /* Bytes per bitplane */
- size=planeoff*bmhd->nplanes; /* Bytes for image data */
-
- /* Alloc memory for image data */
- if (tmin->tmin_Data=AllocMem(size,MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR)) {
- /* Read BODY Chunk */
- if (ReadBODYChunk(iff,bmhd,(UBYTE *) tmin->tmin_Data,bpr,planeoff)) {
- /* Retrieve BMHD chunk values */
- tmid->tmid_Normal.Width=bmhd->w;
- tmid->tmid_Normal.Height=bmhd->h;
- tmid->tmid_Normal.Depth=bmhd->nplanes;
- tmid->tmid_Normal.PlanePick=(1L<<bmhd->nplanes)-1;
-
- /* Copy values to second Image struct */
- tmid->tmid_Selected=tmid->tmid_Normal;
-
- /* Init rest of structure */
- tmid->tmid_Normal.ImageData=tmin->tmin_Data;
- tmid->tmid_Data=tmin;
-
- /* All OK. */
- return(tmid);
- }
- FreeMem(tmin->tmin_Data,size);
- }
- FreeMem(tmin,sizeof(struct TMImageNode));
- }
- }
- }
- }
-
- FreeMem(tmid,sizeof(struct TMImageData));
- }
- return(NULL);
- }
-
- /* Read one ANIM frame */
- static BOOL ReadFrame(struct IFFHandle *iff, struct TMImageData *tmid,
- struct TMImageNode **tminptr, ULONG size, BOOL *int2)
- {
- struct StoredProperty *sp;
-
- DEBUG_PRINTF("IFF: Read ANIM Frame\n");
-
- /* Get ANHD chunk */
- if (sp=FindProp(iff,ID_ILBM,ID_ANHD)) {
- struct AnimHeader *ah=(struct AnimHeader *) sp->sp_Data;
-
- DEBUG_PRINTF("IFF: ANIM Opcode %ld\n",ah->operation);
-
- /* Check anim type (Only type 5 supported) and interleave */
- if ((ah->operation==5) && (ah->interleave<=2)) {
- UBYTE *chunkbuf;
- ULONG chunksize=CurrentChunk(iff)->cn_Size;
-
- DEBUG_PRINTF("IFF: DLTA chunk length %ld\n",chunksize);
-
- /* Alloc buffer for chunk data */
- if (chunkbuf=AllocMem(chunksize,MEMF_PUBLIC)) {
- /* Read chunk data */
- if (ReadChunkBytes(iff,chunkbuf,chunksize)==chunksize) {
- struct TMImageNode *tmin;
-
- DEBUG_PRINTF("IFF: DLTA chunk read\n");
-
- /* Alloc image node */
- if (tmin=AllocMem(sizeof(struct TMImageNode),MEMF_PUBLIC|MEMF_CLEAR)) {
- /* Alloc memory for image data */
- if (tmin->tmin_Data=AllocMem(size,MEMF_PUBLIC|MEMF_CHIP)) {
- ULONG bpr=BPR(tmid->tmid_Normal.Width);
- ULONG rows=tmid->tmid_Normal.Height;
- ULONG planeoff=bpr*rows;
- ULONG pl,planes=tmid->tmid_Normal.Depth;
-
- /* Interleave == 1?? */
- if (ah->interleave==1) {
- /* Yes. ANIM with 1 image interleave (DP ANIM brush). First image? */
- if (!(*tminptr))
- /* Yes. Set pointer. */
- *tminptr=tmid->tmid_Data;
-
- /* Copy old frame to new buffer */
- CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
-
- /* Append new image node to list, move pointer */
- (*tminptr)->tmin_Next=tmin;
- *tminptr=tmin;
- }
- else {
- /* No. ANIM with 2 images interleave. First image? */
-
- if (!(*tminptr)) {
- /* Yes. Set pointer */
- *tminptr=tmid->tmid_Data;
-
- /* Copy old frame to new buffer */
- CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
- } else {
- /* No. Copy old frame to new buffer */
- CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
-
- /* Move pointer */
- *tminptr=(*tminptr)->tmin_Next;
-
- }
-
- /* Append new image node to list */
- (*tminptr)->tmin_Next=tmin;
-
- /* Interleave==2 */
- *int2=TRUE;
- }
-
- DEBUG_PRINTF("chunkbuf 0x%08lx",chunkbuf);
- DEBUG_PRINTF(" imagedata 0x%08lx\n",tmin->tmin_Data);
-
- /* XOR or STORE method? */
- if (ah->bits & 0x2)
- /* Apply DLTA data to frame for each plane with XOR method */
- for (pl=0; pl<planes; pl++) {
- ULONG off=*((ULONG *) chunkbuf+pl);
-
- /* Any data for this plane? */
- if (off) {
- ULONG col;
- register UBYTE *sp=chunkbuf+off;
- UBYTE *plane=(UBYTE *) tmin->tmin_Data+pl*planeoff;
-
- /* For each byte column in this plane */
- for (col=0; col<bpr; col++) {
- UBYTE *dp=plane+col;
- LONG opcount=*sp++;
-
- while (opcount-->0) {
- UBYTE code=*sp++; /* Get code */
-
- if (code==0) {
- /* Same bytes */
- UBYTE count=*sp++;
- UBYTE byte=*sp++;
-
- /* Copy byte count times */
- while (count--) {
- *dp^=byte;
- dp+=bpr; /* next ROW! */
- }
- } else if (code & 0x80) {
- /* Literal copy */
- UBYTE count=code&0x7f; /* Strip high bit */
-
- /* Copy data */
- while (count--) {
- *dp^=*sp++;
- dp+=bpr; /* next ROW! */
- }
- } else
- /* Move destination pointer code rows */
- dp+=code*bpr;
- }
- }
- }
- }
- else
- /* Apply DLTA data to frame for each plane with STORE method */
- for (pl=0; pl<planes; pl++) {
- ULONG off=*((ULONG *) chunkbuf+pl);
-
- /* Any data for this plane? */
- if (off) {
- ULONG col;
- register UBYTE *sp=chunkbuf+*((ULONG *) chunkbuf+pl);
- UBYTE *plane=(UBYTE *) tmin->tmin_Data+pl*planeoff;
-
- /* For each byte column in this plane */
- for (col=0; col<bpr; col++) {
- UBYTE *dp=plane+col;
- LONG opcount=*sp++;
-
- while (opcount-->0) {
- UBYTE code=*sp++; /* Get code */
-
- if (code==0) {
- /* Same bytes */
- UBYTE count=*sp++;
- UBYTE byte=*sp++;
-
- /* Copy byte count times */
- while (count--) {
- *dp=byte;
- dp+=bpr; /* next ROW! */
- }
- } else if (code & 0x80) {
- /* Literal copy */
- UBYTE count=code&0x7f; /* Strip high bit */
-
- /* Copy data */
- while (count--) {
- *dp=*sp++;
- dp+=bpr; /* next ROW! */
- }
- } else
- /* Move destination pointer code rows */
- dp+=code*bpr;
- }
- }
- }
- }
-
- /* All OK! free chunk buffer */
- FreeMem(chunkbuf,chunksize);
- return(TRUE);
- }
- FreeMem(tmin,sizeof(struct TMImageNode));
- }
- }
- FreeMem(chunkbuf,chunksize);
- }
- }
- }
- return(FALSE);
- }
-
- /* Read IFF ANIM Chunk */
- static struct TMImageData *ReadANIMChunk(struct IFFHandle *iff)
- {
- struct TMImageData *tmid=NULL;
-
- DEBUG_PRINTF("IFF: Read ANIM chunk\n");
-
- /* Go to first ILBM chunk */
- if (!ParseIFF(iff,IFFPARSE_STEP)) {
- struct ContextNode *cn;
-
- DEBUG_PRINTF("IFF: Skipped FORM ANIM chunk\n");
-
- /* Get current IFF chunk context, check chunk ID & type, read ILBM chunk */
- if ((cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM) &&
- (cn->cn_Type==ID_ILBM) && (tmid=ReadILBMChunk(iff))) {
-
- ULONG size=BPR(tmid->tmid_Normal.Width) * tmid->tmid_Normal.Height *
- tmid->tmid_Normal.Depth;
- struct TMImageNode *tmin=NULL;
- struct TMImageNode *lasttmin=tmid->tmid_Data;
- struct TMImageNode *last2tmin=NULL;
- struct TMImageNode *last3tmin=NULL;
- BOOL int2=FALSE;
-
- /* Skip rest of current ILBM FORM */
- while (ParseIFF(iff,IFFPARSE_SCAN)==IFFERR_EOC)
- /* Step to next FORM chunk */
- if (!ParseIFF(iff,IFFPARSE_STEP) &&
-
- /* Check type of current chunk */
- (cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM) &&
- (cn->cn_Type==ID_ILBM) &&
-
- /* ANHD: FORM ANIM property chunk */
- !PropChunk(iff,ID_ILBM,ID_ANHD) &&
-
- /* DLTA: FORM ANIM data chunk */
- !StopChunk(iff,ID_ILBM,ID_DLTA) &&
-
- /* FORM: begin of next frame */
- !StopOnExit(iff,ID_ILBM,ID_FORM) &&
-
- /* Start parsing */
- !ParseIFF(iff,IFFPARSE_SCAN) &&
-
- /* Read frame */
- ReadFrame(iff,tmid,&tmin,size,&int2)) {
- /* Move pointer chain */
- last3tmin=last2tmin;
- last2tmin=lasttmin;
- lasttmin=lasttmin->tmin_Next;
- }
- else break;
-
- /* ANIM chunk read */
- /* Delete last (int2==FALSE) or last two (int2==TRUE) frames. */
- /* These frames are unnecessary, because they are duplicates. */
- /* Got at least three nodes? */
- if (last3tmin) {
- /* Yes. Interleave==2 and at least four nodes? */
- if (int2 && (last3tmin!=tmid->tmid_Data)) {
- /* Yes. Delete second to last node */
- FreeMem(last2tmin->tmin_Data,size);
- FreeMem(last2tmin,sizeof(struct TMImageNode));
-
- /* Cut list off after third to last node */
- last3tmin->tmin_Next=NULL;
- } else
- /* No. Cut list off after second to last node */
- last2tmin->tmin_Next=NULL;
-
- /* Delete last node */
- FreeMem(lasttmin->tmin_Data,size);
- FreeMem(lasttmin,sizeof(struct TMImageNode));
- }
-
- /* Init rest of structure */
- if (tmin=tmid->tmid_Data->tmin_Next)
- tmid->tmid_Selected.ImageData=tmin->tmin_Data;
- }
- }
- return(tmid);
- }
-
- /* Read IFF file */
- struct TMImageData *ReadIFFData(char *name)
- {
- struct TMImageData *tmid=NULL;
-
- /* Open IFF parsing library */
- if (IFFParseBase=OpenLibrary("iffparse.library",0)) {
- struct IFFHandle *iff;
-
- DEBUG_PRINTF("IFF Library opened.\n");
-
- /* Alloc IFF handle */
- if (iff=AllocIFF()) {
-
- DEBUG_PRINTF("IFF Handle (0x%08lx)\n",iff);
-
- /* Open IFF file */
- if (iff->iff_Stream=Open(name,MODE_OLDFILE)) {
- /* Init IFF handle */
- InitIFFasDOS(iff);
-
- DEBUG_PRINTF("IFF Stream (0x%08lx)\n",iff->iff_Stream);
-
- /* Open IFF handle */
- if (!OpenIFF(iff,IFFF_READ)) {
-
- DEBUG_PRINTF("IFF Opened\n");
-
- /* Start IFF parsing */
- if (!ParseIFF(iff,IFFPARSE_STEP)) {
- struct ContextNode *cn;
-
- /* Get current IFF chunk context and check for FORM chunk ID */
- if ((cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM))
- /* Yes. Check for FORM type */
- switch (cn->cn_Type) {
- case ID_ILBM:tmid=ReadILBMChunk(iff); /* FORM ILBM file */
- break;
- case ID_ANIM:tmid=ReadANIMChunk(iff); /* FORM ANIM file */
- break;
- }
- }
- CloseIFF(iff);
- }
- Close(iff->iff_Stream);
- }
- FreeIFF(iff);
- }
- CloseLibrary(IFFParseBase);
- }
- return(tmid);
- }
-
- /* Free IFF Data */
- void FreeIFFData(struct TMImageData *tmid)
- {
- struct TMImageNode *tmin1,*tmin2=tmid->tmid_Data;
- ULONG size=BPR(tmid->tmid_Normal.Width) * tmid->tmid_Normal.Height *
- tmid->tmid_Normal.Depth;
-
- /* Free all image datas and nodes */
- while (tmin1=tmin2) {
- /* Get pointer to next node */
- tmin2=tmin1->tmin_Next;
-
- /* Free Image Data */
- FreeMem(tmin1->tmin_Data,size);
-
- /* Free Node */
- FreeMem(tmin1,sizeof(struct TMImageNode));
- }
-
- /* Free main structure */
- FreeMem(tmid,sizeof(struct TMImageData));
- }
-
-